package com.videoweb.controller;

import com.videoweb.model.User;
import com.videoweb.service.UserService;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Slf4j
@RestController
@RequestMapping("/api/auth")
public class UserController {
    
    private final UserService userService;
    private final AuthenticationManager authenticationManager;
    
    public UserController(UserService userService, 
                         AuthenticationManager authenticationManager) {
        this.userService = userService;
        this.authenticationManager = authenticationManager;
    }
    
    @PostMapping("/register")
    public ResponseEntity<?> register(@RequestBody User user, HttpServletRequest request) {
        try {
            // First validate and register the user
            User registeredUser = userService.register(user);
            registeredUser.setPassword(null); // Don't send password back
            
            // Then attempt to log them in
            try {
                Authentication authentication = authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword())
                );
                
                // Set authentication in security context
                SecurityContextHolder.getContext().setAuthentication(authentication);
                
                // Store user in session
                HttpSession session = request.getSession();
                session.setAttribute("currentUser", registeredUser);
                session.setAttribute("authenticated", true);
                
                log.debug("User registered and logged in: {}", registeredUser.getUsername());
                
                Map<String, Object> responseMap = new HashMap<>();
                responseMap.put("user", registeredUser);
                responseMap.put("message", "Registration and login successful");
                
                return ResponseEntity.ok(responseMap);
            } catch (Exception loginException) {
                log.error("Auto-login failed after registration", loginException);
                // If auto-login fails, still return success but without auto-login
                Map<String, Object> responseMap = new HashMap<>();
                responseMap.put("user", registeredUser);
                responseMap.put("message", "Registration successful, but automatic login failed. Please log in manually.");
                return ResponseEntity.ok(responseMap);
            }
        } catch (IllegalArgumentException e) {
            // Validation errors (invalid email, username taken, etc.)
            return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
        } catch (Exception e) {
            // Unexpected errors
            log.error("Registration error", e);
            return ResponseEntity.internalServerError().body(Map.of("error", "An unexpected error occurred"));
        }
    }
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody User loginRequest, HttpServletRequest request) {
        try {
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
            );
            
            // Set authentication in security context
            SecurityContextHolder.getContext().setAuthentication(authentication);
            
            Optional<User> userOpt = userService.getCurrentUser(loginRequest.getUsername());
            if (!userOpt.isPresent()) {
                return ResponseEntity.status(401).body(Map.of("error", "User not found"));
            }
            
            User user = userOpt.get();
            user.setPassword(null);
            
            // Store user in session
            HttpSession session = request.getSession();
            session.setAttribute("currentUser", user);
            session.setAttribute("authenticated", true);
            
            log.debug("User logged in: {}", user.getUsername());
            
            Map<String, Object> responseMap = new HashMap<>();
            responseMap.put("user", user);
            responseMap.put("message", "Login successful");
            
            return ResponseEntity.ok(responseMap);
        } catch (BadCredentialsException e) {
            return ResponseEntity.badRequest().body(Map.of("error", "Invalid username or password"));
        } catch (Exception e) {
            log.error("Login error", e);
            return ResponseEntity.internalServerError().body(Map.of("error", "An unexpected error occurred"));
        }
    }
    
    @PostMapping("/logout")
    public ResponseEntity<?> logout(HttpServletRequest request) {
        try {
            // Clear session
            HttpSession session = request.getSession(false);
            if (session != null) {
                session.invalidate();
            }
            
            // Clear security context
            SecurityContextHolder.clearContext();
            
            log.debug("User logged out");
            
            return ResponseEntity.ok(Map.of("message", "Logged out successfully"));
        } catch (Exception e) {
            log.error("Logout error", e);
            return ResponseEntity.internalServerError().body(Map.of("error", "An error occurred during logout"));
        }
    }
    
    @GetMapping("/user")
    public ResponseEntity<?> getCurrentUser(HttpServletRequest request) {
        try {
            // Check session first
            HttpSession session = request.getSession(false);
            if (session != null) {
                Boolean authenticated = (Boolean) session.getAttribute("authenticated");
                User sessionUser = (User) session.getAttribute("currentUser");
                
                if (Boolean.TRUE.equals(authenticated) && sessionUser != null) {
                    log.debug("User found in session: {}", sessionUser.getUsername());
                    return ResponseEntity.ok(sessionUser);
                }
            }
            
            // Fallback to security context
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            if (auth != null && auth.isAuthenticated() && !auth.getName().equals("anonymousUser")) {
                String username = auth.getName();
                log.debug("Fetching user details from database for username: {}", username);
                
                Optional<User> userOpt = userService.getCurrentUser(username);
                if (userOpt.isPresent()) {
                    User user = userOpt.get();
                    user.setPassword(null);
                    
                    // Update session
                    if (session != null) {
                        session.setAttribute("currentUser", user);
                        session.setAttribute("authenticated", true);
                    }
                    
                    return ResponseEntity.ok(user);
                }
            }
            
            log.debug("No authenticated user found");
            return ResponseEntity.status(401).body(Map.of("error", "Not authenticated"));
            
        } catch (Exception e) {
            log.error("Error in getCurrentUser", e);
            return ResponseEntity.status(500).body(Map.of(
                "error", "An error occurred while fetching user details",
                "message", e.getMessage()
            ));
        }
    }
}
